using System;
using System.Collections.Generic;
using System.Text;
using System.Collections.ObjectModel;

namespace MVCFramework
{
    [Serializable ]
    public class DomainCollection<T> : Collection<T> ,IDomainCollection where T :class
    {
        private static readonly LoggerAdapter  log = new LoggerAdapter (typeof(IDomainCollection));

        public DomainCollection()
        {
            isModelModifiededCollection = true;
        }

        public DomainCollection(bool isModelModifiededCollection) 
        {
            this.isModelModifiededCollection = isModelModifiededCollection;
        }

        public event EventHandler<DomainCollectionChangedEventArgs<object>> OnChange;
        public event EventHandler<EventArgs> OnExternalyChanged;

        protected override void InsertItem(int index, T newItem)
        {
            base.InsertItem(index, newItem);

            EventHandler<DomainCollectionChangedEventArgs<object >> temp = OnChange;
            if (temp != null)
            {
            //    log.Info("Object"+ newItem .ToString ()+" Added to Collection " + this.ToString());

                temp(this, new DomainCollectionChangedEventArgs<object >(
                    ChangeType.Added, newItem, null));
             //   log.Warn(" OnChanged Event  Raised in " + this.ToString());

            }
        }
        protected override void SetItem(int index, T newItem)
        {
            T replaced = Items[index];
            base.SetItem(index, newItem);
          //  log.Info ("Object" + newItem.ToString() + " Added to Collection " + this.ToString());
            EventHandler<DomainCollectionChangedEventArgs<object >> temp = OnChange;
            if (temp != null)
            {
                temp(this, new DomainCollectionChangedEventArgs<object>(
                    ChangeType.Replaced, replaced, newItem));
            //    log.Info (" OnChanged Event  Raised in " + this.ToString());
            }
        }
        protected override void RemoveItem(int index)
        {
            T removedItem = Items[index];

            base.RemoveItem(index);

            EventHandler<DomainCollectionChangedEventArgs<object>> temp = OnChange;
            if (temp != null)
            {
              //  log.Info ("Object Removed from Collection " + this.ToString());

                temp(this, new DomainCollectionChangedEventArgs<object>(
                    ChangeType.Removed, removedItem, null));
            }
        }
        protected override void ClearItems()
        {

            List<object> objects = new List<object>();
            foreach ( object _object in this)
                objects.Add(_object);

            base.ClearItems();

            EventHandler<DomainCollectionChangedEventArgs<object>> temp = OnChange;
            if (temp != null)
            {
             //   log.Warn (" Collection is Cleaned " + this.ToString());

                temp(this, new DomainCollectionChangedEventArgs<object>(
                    ChangeType.Cleared, objects ));
            }
        }

        #region IDomainCollection Members

        /// <summary>
        /// if ModelModifieded collection is Set true then model sends a notification to collection 
        /// and the coolection is responsible to remove or add the meber 
        /// Else the model is responsible to  modify  the collection.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="args"></param>
        public void ModelModifiedCollectionHandler(object sender, ModelModificationEventArgs args)
        {
            if (isModelModifiededCollection == false) return;
            if (args.Changetype == ModelChangeType .Removed )
                if (this.Contains(args.Modified as T))
                {
                    int index = base.IndexOf(args.Modified as T);
                    base.RemoveItem (index);

               //    log.Warn (" Collection Modifidied Externaly by "+sender .ToString () + " methods Called");
                  if (OnExternalyChanged != null)
                  {
                      Delegate[] _delegate = OnExternalyChanged.GetInvocationList();
                      for (int i = 0; i < _delegate.Length; i++)
                          log.Warn("Methode Called" + _delegate[i].ToString());
                      OnExternalyChanged(this, new DomainCollectionChangedEventArgs<object>(ChangeType.Removed, args.Modified, null)); 
                  }
                }
        }

        #endregion
        #region IDomainCollection Members

        bool isModelModifiededCollection;
        public bool IsModelModifiededCollection
        {
            get
            {
                return isModelModifiededCollection;
            }
            set
            {
                isModelModifiededCollection = value;
            }
        }

        public override string ToString()
        {
            return "Collection of " + typeof(T).ToString();
        }
        #endregion
    }
    public class DomainCollectionChangedEventArgs<T> : EventArgs
    {
        public readonly T ChangedItem;
        public readonly ChangeType ChangeType;
        public readonly T ReplacedWith;

        public DomainCollectionChangedEventArgs(ChangeType change, T item,
            T replacement)
        {
            ChangeType = change;
            ChangedItem = item;
            ReplacedWith = replacement;

        }
                public readonly List<T> items;

        public DomainCollectionChangedEventArgs(ChangeType change, List<T> items)
        {
            ChangeType = change;
            this.items  = items;

        }

    }
}
